package com.google.jacli;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public final class CommandLineParser {
    public static final String DEFAULT_PREFIX = "--";
    public static final String DEFAULT_SHORT_PREFIX = "-";

    private CommandLineParser() {
        // empty
    }


    private static CommandLine getCommandLine(Object target) {
        CommandLine command = new CommandLine();
        command.setBean(target);

        List<Field> fields = getAllDeclaredFields(target.getClass());

        List<Field> fieldList = command.getFields();

        if (fields != null) {
            for (Field field : fields) {
                Argument argument = getArgument(field);
                if (argument == null) {
                    continue;
                }
                if (argument.option().length() > 0) {
                    command.setPattern(Pattern.OPT);
                }
                try {
                    if (null != fieldList.get(argument.id())) {
                        command.getExceptions().add(new IllegalArgumentException("Argument position # "
                                                                                 + argument.id()
                                                                                 + " already occupied!"));
                    }
                } catch (Exception e) {
                    // ignore
                }
                fieldList.add(field);
            }
        }
        return command;
    }

    public static CommandLine parse(Object obj, String[] args) {
        return parse(obj, args, DEFAULT_SHORT_PREFIX, DEFAULT_SHORT_PREFIX);
    }

    public static CommandLine parse(Object obj, String[] args, String prefix) {
        return parse(obj, args, prefix, prefix);
    }
    
    public static CommandLine parse(Object obj, String[] args, String prefix, String shortPrefix) {
        CommandLine command = getCommandLine(obj);
        command.setPrefix(prefix);
        command.setShortPrefix(shortPrefix);

        if (args == null || args.length == 0) {
            return command;
        }

        List<Field>fieldList = command.getFields();

        if (fieldList == null) {
            System.err.println("No arguments found");
        }
        
        command.getPattern().compile(fieldList, obj, args);
        
        return command;
    }

    public static Argument getArgument(final Field field) {
        return (Argument) field.getAnnotation(Argument.class);
    }

    public static List<Field> getAllDeclaredFields(Class target) {
        List<Field> fields = new ArrayList<Field>();
        for (Class clz : getAllSuperClasses(target)) {
            fields.addAll(Arrays.asList(clz.getDeclaredFields()));
        }
        return fields;
    }
    
    public static List<Class> getAllSuperClasses(Class target) {
        List<Class> superClasses = new ArrayList<Class>();
        Class<?> pClass = target;

        while (pClass != Object.class) {
            superClasses.add(pClass);
            pClass = pClass.getSuperclass();
        }
        return superClasses;
    }
}